home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Kit PC World De Ampliacion De Windows 95
/
Kit PC World de ampliacion de Windows 95.iso
/
internet
/
sweeper
/
samples
/
olecon~1
/
controls
/
button
/
button~1.cpp
< prev
next >
Wrap
Text File
|
1995-11-28
|
18KB
|
644 lines
//=--------------------------------------------------------------------------=
// ButtonCtl.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
#include "IPServer.H"
#include "Guids.H"
#include "ButtonCtl.H"
#include "LocalObj.H"
#include "Util.H"
#include "Globals.H"
#include "Resource.H"
#include <windowsx.h>
// for ASSERT and FAIL
//
SZTHISFILE
// local private functions
//
short _GetShiftState(void);
// these are used for events
//
#define LEFT_BUTTON 0x01
#define RIGHT_BUTTON 0x02
#define MIDDLE_BUTTON 0x04
//=--------------------------------------------------------------------------=
// for persistence
//
#define STREAMHDR_MAGIC 0x12345678
typedef struct {
DWORD dwMagic;
DWORD dwVersion;
DWORD cbSize;
} STREAMHDR;
WCHAR wszCaption [] = L"Caption";
//=--------------------------------------------------------------------------=
// all the events in this control
//
// TODO: add events here ...
//
VARTYPE rgI2I2I4I4 [] = { VT_I2, VT_I2, VT_I4, VT_I4 };
typedef enum {
ButtonEvent_Click = 0,
ButtonEvent_DblClick = 1,
ButtonEvent_MouseDown = 2,
ButtonEvent_MouseMove = 3,
ButtonEvent_MouseUp = 4
} BUTTONEVENTS;
EVENTINFO m_rgEvents [] = {
{ DISPID_CLICK, 0, NULL },
{ DISPID_DBLCLICK, 0, NULL },
{ DISPID_MOUSEDOWN, 4, rgI2I2I4I4 },
{ DISPID_MOUSEMOVE, 4, rgI2I2I4I4 },
{ DISPID_MOUSEUP, 4, rgI2I2I4I4 },
};
//=--------------------------------------------------------------------------=
// array describing all of our property pages. these clsids are typically
// in guids.h
//
// TODO: add any additional property page guids here ...
//
const GUID *rgButtonPropPages [] = {
&CLSID_ButtonGeneralPage
};
//=--------------------------------------------------------------------------=
// Custum Verb information
//
// TODO: add any custom verbs here in an array, using the VERBINFO structure.
// then mark the controld def'n in ButtonCtl.H with
// this verb array
//
//=--------------------------------------------------------------------------=
// CButtonControl::Create
//=--------------------------------------------------------------------------=
// global static function that creates an instance of the control an returns
// an IUnknown pointer for it.
//
// Parameters:
// IUnknown * - [in] controlling unknown for aggregation
//
// Output:
// IUnknown * - new object.
//
// Notes:
//
IUnknown *CButtonControl::Create
(
IUnknown *pUnkOuter
)
{
// make sure we return the private unknown so that we support aggegation
// correctly!
//
CButtonControl *pNew = new CButtonControl(pUnkOuter);
return pNew->PrivateUnknown();
}
//=--------------------------------------------------------------------------=
// CButtonControl::CButtonControl
//=--------------------------------------------------------------------------=
// "Being born is like being kidnapped. And then sold into slavery."
// - andy warhol (1928 - 87)
//
// Parameters:
// IUnknown * - [in]
//
// Notes:
//
#pragma warning(disable:4355) // using 'this' in constructor
CButtonControl::CButtonControl
(
IUnknown *pUnkOuter
)
: COleControl(pUnkOuter, OBJECT_TYPE_CTLBUTTON, (IDispatch *)this)
{
// zero out the persistent state structure.
//
memset(&m_state, 0, sizeof(BUTTONCTLSTATE));
// TODO: initialize anything you need to here.
//
lstrcpy(m_state.szCaption, "Button");
}
#pragma warning(default:4355) // using 'this' in constructor
//=--------------------------------------------------------------------------=
// CButtonControl::~CButtonControl
//=--------------------------------------------------------------------------=
// "We all labour against our own cure, for death is the cure of all diseases"
// - Sir Thomas Browne (1605 - 82)
//
// Notes:
//
CButtonControl::~CButtonControl ()
{
// TODO: clean up anything here.
}
//=--------------------------------------------------------------------------=
// CButtonControl:RegisterClassData
//=--------------------------------------------------------------------------=
// register the window class information for your control here.
// this information will automatically get cleaned up for you on DLL shutdown.
//
// Output:
// BOOL - FALSE means fatal error.
//
// Notes:
//
BOOL CButtonControl::RegisterClassData
(
void
)
{
WNDCLASS wndclass;
// subclass a windows BUTTON control.
//
if (!::GetClassInfo(g_hInstance, "BUTTON", &wndclass))
return FALSE;
SUBCLASSWNDPROCOFCONTROL(OBJECT_TYPE_CTLBUTTON) = (WNDPROC)wndclass.lpfnWndProc;
wndclass.lpfnWndProc = COleControl::ControlWindowProc;
wndclass.lpszClassName = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLBUTTON);
return RegisterClass(&wndclass);
}
//=--------------------------------------------------------------------------=
// CButtonControl::BeforeCreateWindow
//=--------------------------------------------------------------------------=
// called just before the window is created. Great place to set up the
// window title, etc, so that they're passed in to the call to CreateWindowEx.
// speeds things up slightly.
//
// Notes:
//
void CButtonControl::BeforeCreateWindow
(
void
)
{
// TODO: users should modify m_dwWindowStyle, m_dwWindowStyleEx, m_szWindowTitle
// et al here so that the call to createwindow has as much information as
// possible.
// if you don't use this function, then you can probably just remove it.
//
m_szWindowTitle = m_state.szCaption;
}
//=--------------------------------------------------------------------------=
// CButtonControl::AfterCreateWindow
//=--------------------------------------------------------------------------=
// we have to override this so we can set up the font from the hosts
// ambient font.
//
// Notes:
//
void CButtonControl::AfterCreateWindow
(
void
)
{
IFont *pFont;
HFONT hFont;
// get the HFONT for the form's ambient font.
//
GetAmbientFont(&pFont);
pFont->get_hFont(&hFont);
SendMessage(m_hwnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
pFont->Release();
}
//=--------------------------------------------------------------------------=
// CButtonControl::InternalQueryInterface
//=--------------------------------------------------------------------------=
// qi for things only we support.
//
// Parameters:
// Parameters:
// REFIID - [in] interface they want
// void ** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CButtonControl::InternalQueryInterface
(
REFIID riid,
void **ppvObjOut
)
{
IUnknown *pUnk;
*ppvObjOut = NULL;
// TODO: if you want to support any additional interrfaces, then you should
// indicate that here. never forget to call COleControl's version in the
// case where you don't support the given interface.
//
if (DO_GUIDS_MATCH(riid, IID_IButton)) {
pUnk = (IUnknown *)(IButton *)this;
} else{
return COleControl::InternalQueryInterface(riid, ppvObjOut);
}
pUnk->AddRef();
*ppvObjOut = (void *)pUnk;
return S_OK;
}
//=--------------------------------------------------------------------------=
// CButtonControl::LoadTextState
//=--------------------------------------------------------------------------=
// load in our text state for this control.
//
// Parameters:
// IPropertyBag * - [in] property bag to read from
// IErrorLog * - [in] errorlog object to use with proeprty bag
//
// Output:
// HRESULT
//
// Notes:
// - NOTE: if you have a binary object, then you should pass an unknown
// pointer to the property bag, and it will QI it for IPersistStream, and
// get said object to do a Load()
//
STDMETHODIMP CButtonControl::LoadTextState
(
IPropertyBag *pPropertyBag,
IErrorLog *pErrorLog
)
{
VARIANT v;
v.vt = VT_BSTR;
v.bstrVal = NULL;
// try to load in the property. if we can't get it, then leave
// things at their default.
//
pPropertyBag->Read(wszCaption, &v, pErrorLog);
if (v.bstrVal) {
MAKE_ANSIPTR_FROMWIDE(psz, v.bstrVal);
lstrcpyn(m_state.szCaption, psz, sizeof(m_state.szCaption));
VariantClear(&v);
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// CButtonControl::LoadBinaryState
//=--------------------------------------------------------------------------=
// loads in our binary state using streams.
//
// Parameters:
// IStream * - [in] stream to write to.
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CButtonControl::LoadBinaryState
(
IStream *pStream
)
{
STREAMHDR sh;
HRESULT hr;
// first read in the streamhdr, and make sure we like what we're getting
//
hr = pStream->Read(&sh, sizeof(sh), NULL);
RETURN_ON_FAILURE(hr);
// sanity check
//
if (sh.dwMagic != STREAMHDR_MAGIC || sh.cbSize != sizeof(m_state))
return E_UNEXPECTED;
// read in the control state information
//
hr = pStream->Read(&(m_state), sizeof(m_state), NULL);
RETURN_ON_FAILURE(hr);
return S_OK;
}
//=--------------------------------------------------------------------------=
// CButtonControl::SaveTextState
//=--------------------------------------------------------------------------=
// saves out the text state for this control using a property bag.
//
// Parameters:
// IPropertyBag * - [in] the property bag with which to work.
// BOOL - [in] if TRUE, then write out ALL properties, even
// if they're their the default value ...
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CButtonControl::SaveTextState
(
IPropertyBag *pPropertyBag,
BOOL fWriteDefaults
)
{
HRESULT hr;
VARIANT v;
v.vt = VT_BSTR;
v.bstrVal = BSTRFROMANSI(m_state.szCaption);
RETURN_ON_NULLALLOC(v.bstrVal);
// this control currently only persists out the caption property
//
hr = pPropertyBag->Write(wszCaption, &v);
VariantClear(&v);
return hr;
}
//=--------------------------------------------------------------------------=
// CButtonControl::SaveBinaryState
//=--------------------------------------------------------------------------=
// save out the binary state for this control, using the given IStream object.
//
// Parameters:
// IStream * - [in] save to which you should save.
//
// Output:
// HRESULT
//
// Notes:
// - it is important that you seek to the end of where you saved your
// properties when you're done with the IStream.
//
STDMETHODIMP CButtonControl::SaveBinaryState
(
IStream *pStream
)
{
STREAMHDR sh = { STREAMHDR_MAGIC, MAKELONG(1, 0), sizeof(m_state) };
HRESULT hr;
// write out the stream hdr.
//
hr = pStream->Write(&sh, sizeof(sh), NULL);
RETURN_ON_FAILURE(hr);
// write out he control state information
//
hr = pStream->Write(&m_state, sizeof(m_state), NULL);
return hr;
}
//=--------------------------------------------------------------------------=
// CButtonControl::OnDraw
//=--------------------------------------------------------------------------=
// "I don't very much enjoy looking at paintings in general. i know too
// much about them. i take them apart."
// - georgia o'keeffe (1887-1986)
//
// Parameters:
// HDC - [in] HDC to draw to
// LPCRECTL - [in] rect we're drawing to
// LPCRECTL - [in] window extent and origin for meta-files
// HDC - [in] HIC for target device
//
// Output:
// HRESULT
//
// Notes:
//
HRESULT CButtonControl::OnDraw
(
HDC hdcDraw,
LPCRECTL prcBounds,
LPCRECTL prcWBounds,
HDC hicTargetDevice
)
{
// TODO: put your drawing code here ...
//
return DoSuperClassPaint(hdcDraw, prcBounds);
}
//=--------------------------------------------------------------------------=
// CButtonControl::WindowProc
//=--------------------------------------------------------------------------=
// window procedure for this control. nothing terribly exciting.
//
// Parameters:
// see win32sdk on window procs.
//
// Notes:
//
LRESULT CButtonControl::WindowProc
(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
switch (msg) {
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
{
short s = (msg == WM_LBUTTONDOWN) ? LEFT_BUTTON : ((msg == WM_RBUTTONDOWN) ? RIGHT_BUTTON : MIDDLE_BUTTON);
FireEvent(&(m_rgEvents[ButtonEvent_MouseDown]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
}
break;
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
FireEvent(&(m_rgEvents[ButtonEvent_DblClick]));
break;
case WM_RBUTTONUP:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
{
short s = (msg == WM_LBUTTONUP) ? LEFT_BUTTON : ((msg == WM_RBUTTONUP) ? RIGHT_BUTTON : MIDDLE_BUTTON);
FireEvent(&(m_rgEvents[ButtonEvent_MouseUp]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
}
break;
case WM_MOUSEMOVE:
{
short s = (wParam & MK_LBUTTON) ? LEFT_BUTTON : ((wParam & MK_RBUTTON) ? RIGHT_BUTTON : ((wParam & MK_MBUTTON) ? MIDDLE_BUTTON : 0));
FireEvent(&(m_rgEvents[ButtonEvent_MouseMove]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
}
break;
case OCM_COMMAND:
switch (LOWORD(wParam)) {
case BN_CLICKED:
FireEvent(&(m_rgEvents[ButtonEvent_Click]));
break;
}
break;
}
// pass anything else on to the superproc.
//
return CallWindowProc((FARPROC)SUBCLASSWNDPROCOFCONTROL(OBJECT_TYPE_CTLBUTTON), hwnd, msg, wParam, lParam);
}
//=--------------------------------------------------------------------------=
// CButtonControl::AboutBox
//=--------------------------------------------------------------------------=
// prints up an about box. fweeeee.
//
// Notes:
//
void CButtonControl::AboutBox
(
void
)
{
// TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
// they wanted a slightly more interesting About Box ... you should
// still call ModalDialog first, however.
//
ModalDialog(TRUE);
MessageBox(NULL, "This is My Control", "About Button", MB_OK | MB_TASKMODAL);
ModalDialog(FALSE);
}
//=--------------------------------------------------------------------------=
// CButtonControl::get_Caption [IButton]
//=--------------------------------------------------------------------------=
// returns current caption
//
// Parameters:
// BSTR * - [out] duh
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CButtonControl::get_Caption
(
BSTR *pbstrCaption
)
{
CHECK_POINTER(pbstrCaption);
*pbstrCaption = (*m_state.szCaption) ? BSTRFROMANSI(m_state.szCaption) : SysAllocString(L"");
return (*pbstrCaption) ? S_OK : E_OUTOFMEMORY;
}
//=--------------------------------------------------------------------------=
// CButtonControl::put_Caption [IButton]
//=--------------------------------------------------------------------------=
// sets the new caption
//
// Parameters:
// BSTR - [in] duh
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CButtonControl::put_Caption
(
BSTR bstrCaption
)
{
// get an ANSI pointer, so we can stuff it in our local buffer for captions!
//
if (!bstrCaption) bstrCaption = L"";
MAKE_ANSIPTR_FROMWIDE(pszCaption, bstrCaption);
// if it hasn't changed, don't waste any time.
//
if (!lstrcmp(m_state.szCaption, pszCaption))
return S_OK;
// copy it over
//
lstrcpyn(m_state.szCaption, pszCaption, sizeof(m_state.szCaption));
// update the window, if appropriate.
//
if (m_hwnd) {
Button_SetText(m_hwnd, m_state.szCaption);
InvalidateControl(NULL);
}
// update anybody who cares about property changes and mark ourselves
// as dirty
//
PropertyChanged(DISPID_CAPTION);
m_fDirty = TRUE;
return S_OK;
}
//=--------------------------------------------------------------------------=
// _GetShiftState [standard helper!]
//=--------------------------------------------------------------------------=
// used by people to get shift state information
//
// Output:
// short - mask of shift, ctrl and alt keys
//
// Notes:
//
short _GetShiftState
(
void
)
{
BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
BOOL bCtrl = (GetKeyState(VK_CONTROL) < 0);
BOOL bAlt = (GetKeyState(VK_MENU) < 0);
return (short)(bShift + (bCtrl << 1) + (bAlt << 2));
}